class MyPromise {
    constructor(executor) {
        this.PromiseState = 'pending'
        this.PromiseResult = null
        this.callbacks = []
        const resolve = value => {
            if (this.PromiseState !== 'pending') return
            this.PromiseState = 'fulfilled'
            this.PromiseResult = value
            setTimeout(() => {
                this.callbacks.forEach(item => {
                    item.onResolved(value)
                })
            })
        }
        const reject = reason => {
            if (this.PromiseState !== 'pending') return
            this.PromiseState = 'rejected'
            this.PromiseResult = reason
            setTimeout(() => {
                this.callbacks.forEach(item => {
                    item.onRejected(reason)
                })
            })
        }
        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }
    // 静态方法
    deferred () {
        var result = {};
        result.promise = new MyPromise(function(resolve, reject){
          result.resolve = resolve;
          result.reject = reject;
        });
       
        return result;
    }

    then(onResolved, onRejected) {
        if (typeof onRejected !== 'function') {
            onRejected = reason => { throw reason }
        }
        if (typeof onResolved !== 'function') {
            onResolved = value => value
        }
        return new MyPromise((resolve, reject) => {
            const callback = (type) => {
                try {
                    const res = type(this.PromiseResult)
                    if (res instanceof MyPromise) {
                        res.then(v => {
                            resolve(v)
                        }, r => {
                            reject(r)
                        })
                    } else {
                        resolve(res)
                    }
                } catch (error) {
                    reject(error)
                }
            }
            if (this.PromiseState === 'fulfilled') {
                setTimeout(() => {
                    callback(onResolved)
                })
            }
            if (this.PromiseState === 'rejected') {
                setTimeout(() => {
                    callback(onRejected)
                })
            }
            if (this.PromiseState === 'pending') {
                this.callbacks.push({
                    onResolved: () => {
                        callback(onResolved)
                    },
                    onRejected: () => {
                        callback(onRejected)
                    }
                })
            }
        })
    }

    catch() {
        return this.then(undefined, onRejected)
    }

    static resolve(value) {
        return new MyPromise((resolve, reject) => {
            if (value instanceof MyPromise) {
                value.then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            } else {
                resolve(value)
            }
        })
    }

    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }

    static all(promises) {
        return new MyPromise((resolve, reject) => {
            let count = 0
            let arr = []
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    count++
                    arr[i] = v
                    if (count === promises.length) {
                        resolve(arr)
                    }
                }, r => {
                    reject(r)
                })
            }
        })
    }

    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            }
        })
    }
}

module.exports = MyPromise

